package boardInfo

import (
	"context"
	"fmt"
	"net"
	"time"
)

type handleFunc func([]byte, *stConnect)

type stConnect struct {
	conn   net.Conn
	ctx    context.Context
	cancel context.CancelFunc
	hour   int
	index  int

	wc chan []byte

	handle map[uint16]handleFunc
}

func getConnect(c net.Conn) *stConnect {
	conn := &stConnect{
		conn: c,
	}
	conn.wc = make(chan []byte, 100)
	conn.ctx, conn.cancel = context.WithCancel(context.TODO())
	conn.handle = make(map[uint16]handleFunc)
	conn.handle[6100] = handleBoardInfo
	return conn
}

func (conn *stConnect) closeConnect() {
	conn.cancel()
}

// 接收推送消息
func (conn *stConnect) receivePacket() {
	defer gsf.removeConnect(conn)
	for {

		//_ = conn.conn.SetReadDeadline(time.Now().Add(time.Second * 10))

		head := make([]byte, CHeadSize)
		_, err := conn.conn.Read(head)
		if err != nil {
			//strErr := err.Error()
			//idx := strings.Index(strErr, "i/o timeout")
			//if idx >= 0 {
			//	continue
			//}
			fmt.Println(err.Error())
			return
		}

		var sh StPacketHead
		sh.DeCode(head)

		sh.DwBodyLen -= CHeadSize
		fmt.Printf("receivePacket connect_index=%d bodySize=%d WPid=%d \n", conn.index, sh.DwBodyLen, sh.WPid)

		var btBody []byte
		if sh.DwBodyLen > 0 {
			btBody = make([]byte, sh.DwBodyLen)
			readSize := 0
			for readSize < int(sh.DwBodyLen) {
				m, err := conn.conn.Read(btBody[readSize:])
				if err != nil {
					fmt.Printf("receivePacket connect_index=%d error=%v\n", conn.index, err)
					return
				}
				readSize += m
			}
			//fmt.Printf("receivePacket end connect_index=%d totalSize=%d\n", conn.index, readSize)
		}

		//心跳包 直接发送
		if sh.WPid == 100 {
			head = append(head, btBody...)
			conn.wc <- head
			continue
		}

		handle, have := conn.handle[sh.WPid]
		if have {
			go handle(btBody, conn)
		}
	}
}

// 定时发送请求包
func (conn *stConnect) startTickTask() {

	ticker := time.NewTicker(30 * time.Second)
	defer ticker.Stop()
	for {
		select {
		case <-ticker.C:
			conn.sendReq()
		case <-conn.ctx.Done():
			break
		}
	}
}

// 发送数据包
func (conn *stConnect) writePacket() {

	for {
		select {
		case pack := <-conn.wc:
			_ = conn.writeData(pack)
		case <-conn.ctx.Done():
			break
		}
	}
}

// 下午9点发送一次请求数据包
func (conn *stConnect) sendReq() {
	//now := time.Now()
	//if now.Hour() != 21 || conn.hour == 21 {
	//	conn.hour = now.Hour()
	//	return
	//}
	//
	//conn.hour = now.Hour()

	//1、必然不分的（必除板块）是 2254+2266+2265
	//2、可选择性的分下去的（财务风险板块）是2255+2268
	//BR01FULL0
	req := &stReqSmallFile{wTypeId: 3000, szFileName: "BR01FULL16"}
	_ = conn.sendPacket(req, 6100)
}

// 将数据打包成byte
func (conn *stConnect) sendPacket(pack IEnCode, pid uint16) error {
	bt := pack.EnCode()
	dataLen := len(bt) + CHeadSize
	head := StPacketHead{WPid: pid, DwBodyLen: uint32(dataLen)}
	wbt := head.EnCode()
	wbt = append(wbt, bt...)

	conn.wc <- wbt

	return nil
}

// 将数据写入网络套接字
func (conn *stConnect) writeData(b []byte) error {

	length := len(b)
	n := 0
	for n < length {
		m, err := conn.conn.Write(b[n:])
		if err != nil {
			return fmt.Errorf("c.Write(): %v", err)
		}
		n += m
	}

	return nil
}
